﻿using FxFlowWindowBase.Win.Extension;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace FxFlowWindowBase.Win
{
	/// <summary>
	/// FlowWindow.xaml 的交互逻辑
	/// </summary>
	public partial class FlowWindow : Window
	{

		/// <summary>
		/// 窗体标题
		/// </summary>
		public new string Title
		{
			get => tb_title.Text;
			set => tb_title.Text = value;
		}

		/// <summary>
		/// 窗体是否已经关闭
		/// </summary>
		public bool IsClosed { get; private set; }

		/// <summary>
		/// 是否是用户手动关闭
		/// </summary>
		public bool IsUserClose { get; protected set; }

		/// <summary>
		/// 是否自动滚动到底部
		/// </summary>
		public bool AutoScrollToEnd { get; set; } = true;

		/// <summary>
		/// 滚动区域实际高度
		/// </summary>
		public double ScrollContentHeight => sv.ActualHeight;

		/// <summary>
		/// 滚动读取实际宽度
		/// </summary>
		public double ScrollContentWidth => sv.ActualWidth;

		public FlowWindow()
		{
			// InitializeComponent();
			this.LoadViewFromUri("/FxFlowWindowBase;component/Win/FlowWindow.xaml");
			this.Closed += (sender, args) => IsClosed = true;
			tb_title.MouseLeftButtonDown += (sender, args) => this.DragMove();
			// 清空应用级默认样式的影响
			Application.Current.Resources.Clear();
		}

		/// <summary>
		/// 添加组件
		/// </summary>
		/// <param name="element">组件对象</param>
		internal void AddChild(UIElement element)
		{
			this.panel.Children.Add(element);
			if (AutoScrollToEnd)
			{
				sv.ScrollToEnd();
			}
		}

		/// <summary>
		/// 显示遮罩层加载窗
		/// </summary>
		/// <param name="msg">加载消息</param>
		public void ShowLoading(string msg)
		{
			load_msg_tbx.Text = msg;
			mark.Visibility = Visibility.Visible;
		}

		/// <summary>
		/// 关闭遮罩层
		/// </summary>
		public void CloseLoading()
		{
			mark.Visibility = Visibility.Collapsed;
		}

		/// <summary>
		/// 移除指定名称的控件
		/// </summary>
		/// <param name="name">控件名移</param>
		public void RemoveControl(string name)
		{
			UIElement targetEle = null;
			foreach (UIElement child in panel.Children)
			{
				if (child is FrameworkElement ele && ele.Name == name)
				{
					targetEle = ele;
					break;
				}
			}

			if (targetEle != null)
			{
				panel.Children.Remove(targetEle);
			}
		}


		/// <summary>
		/// 移除匹配指定正则表达式的所有控件
		/// </summary>
		/// <param name="pattern">正则表达式</param>
		public void RemoveControlsByRegex(string pattern)
		{
			List<UIElement> willRemoveEles = new List<UIElement>();
			foreach (UIElement child in panel.Children)
			{
				if (child is FrameworkElement ele)
				{
					if (Regex.IsMatch(ele.Name, pattern))
					{
						willRemoveEles.Add(ele);
					}
				}
			}
			willRemoveEles.ForEach(ele => panel.Children.Remove(ele));
		}

		/// <summary>
		/// 移除所有控件
		/// </summary>
		public void RemoveAllControl()
		{
			panel.Children.Clear();
		}

		/// <summary>
		/// 在指定的panel中获取指定的UI组件
		/// </summary>
		/// <param name="panel">父面板</param>
		/// <param name="name">控件名</param>
		/// <returns>找到的控件</returns>
		private UIElement FindViewInPanel(Panel panel, string name)
		{
			foreach (UIElement child in panel.Children)
			{
				if (child is FrameworkElement element)
				{
					if (element.Name == name)
					{
						return child;
					}

					if (child is Panel childPanel)
					{
						UIElement res = FindViewInPanel(childPanel, name);
						if (res != null)
						{
							return res;
						}
					}
				}
			}
			return null;
		}

		// 根据Name获取控件
		public object FindViewByName(string name)
		{
			return FindViewInPanel(panel, name);
		}

		public void ReplaceControl(string name, UIElement newElement)
		{
			Queue<Panel> panels = new Queue<Panel>();
			panels.Enqueue(panel);
			while (panels.Count > 0)
			{
				Panel curPanel = panels.Dequeue();
				for (var i = 0; i < curPanel.Children.Count; i++)
				{
					UIElement element = curPanel.Children[i];
					if (element is Panel newPanel)
					{
						panels.Enqueue(newPanel);
						continue;
					}

					if (element is FrameworkElement fe && fe.Name == name)
					{
						curPanel.Children.RemoveAt(i);
						curPanel.Children.Insert(i, newElement);
						return;
					}
				}
			}
		}

		/// <summary>
		/// 在指定的panel中获取指定的UI组件集
		/// </summary>
		/// <param name="panel">父面板</param>
		/// <param name="name">控件名正则</param>
		/// <returns>找到的控件集</returns>
		private List<object> FindViewsInPanelByRegex(Panel panel, string regexString)
		{
			List<object> list = new List<object>();
			Regex regex = new Regex(regexString);
			foreach (UIElement child in panel.Children)
			{
				if (child is FrameworkElement element)
				{
					if (regex.IsMatch(element.Name))
					{
						list.Add(child);
						continue;
					}

					if (child is Panel childPanel)
					{
						list.AddRange(FindViewsInPanelByRegex(childPanel, regexString));
					}
				}
			}
			return list;
		}

		/// <summary>
		/// 根据正则查找控件组
		/// </summary>
		/// <param name="regex">正则</param>
		/// <returns>控件组</returns>
		public List<object> FindViewByRegex(string regex)
		{
			return FindViewsInPanelByRegex(panel, regex);
		}

		// 关闭窗体
		private void btn_close_Click(object sender, RoutedEventArgs e)
		{
			IsUserClose = true;
			this.Close();
		}

		// 设置点击关闭按钮事件
		public void SetOnCloseEvent(Action e)
		{
			btn_close.Click += (sender, args) => e?.Invoke();
		}

		// 设置窗体关闭前事件
		public void SetOnBeforeCloseEvent(Func<bool> onBoforeClose)
		{
			if (onBoforeClose == null) return;
			this.Closing += (sender, args) =>
			{
				args.Cancel = onBoforeClose.Invoke();
			};
		}

		// 设置窗体关闭后事件
		public void SetOnClosedEvent(Action e)
		{
			this.Closed += (sender, args) => e?.Invoke();
		}

		// 添加text文本标签
		public void AddText(string name, string text, string fontColor, string backColor, int textAlign = 1)
		{
			TextBlock textBlock = new TextBlock();
			textBlock.Name = name;
			textBlock.Text = text;
			textBlock.Foreground = new SolidColorBrush(ParseColorStr(fontColor));
			textBlock.Background = new SolidColorBrush(ParseColorStr(backColor));
			textBlock.Padding = new Thickness(0, 2, 0, 2);
			switch (textAlign)
			{
				case 0:
					textBlock.TextAlignment = TextAlignment.Left;
					break;
				case 1:
					textBlock.TextAlignment = TextAlignment.Center;
					break;
				case 2:
					textBlock.TextAlignment = TextAlignment.Right;
					break;
				default:
					textBlock.TextAlignment = TextAlignment.Justify;
					break;
			}
			AddChild(textBlock);
		}

		// 添加button组件
		public void AddButton(string name, string text, string fontColor, string backcolor, int align, Action<string> clickEvent)
		{
			Button button = new Button()
			{
				Name = name,
				Content = text,
				Foreground = new SolidColorBrush(ParseColorStr(fontColor)),
				Background = new SolidColorBrush(ParseColorStr(backcolor)),
				Padding = new Thickness(0, 1, 0, 1),
				Focusable = false
			};
			switch (align)
			{
				case 0:
					button.HorizontalContentAlignment = HorizontalAlignment.Left;
					break;
				case 1:
					button.HorizontalContentAlignment = HorizontalAlignment.Center;
					break;
				case 2:
					button.HorizontalContentAlignment = HorizontalAlignment.Right;
					break;
				default:
					button.HorizontalContentAlignment = HorizontalAlignment.Stretch;
					break;
			}
			button.Click += (sender, args) => clickEvent?.Invoke((sender as Button).Name);
			AddChild(button);
		}

		// 添加输入框组件
		public void AddTextbox(string name, string text, string foreColor, string backColor, Action<string> textChangeAction)
		{
			TextBox tbx = new TextBox()
			{
				Name = name,
				Text = text,
				Foreground = new SolidColorBrush(ParseColorStr(foreColor)),
				Background = new SolidColorBrush(ParseColorStr(backColor))
			};
			tbx.TextWrapping = TextWrapping.NoWrap;
			tbx.TextChanged += (sender, args) => textChangeAction?.Invoke(tbx.Text);
			AddChild(tbx);
		}

		// 添加进度条
		public void AddProgressbar(string name, int defaultVal, string foreColor, string backColor, Action<double> valueChange)
		{
			if (defaultVal < 0) defaultVal = 0;
			if (defaultVal > 100) defaultVal = 100;
			ProgressBar progressBar = new ProgressBar()
			{
				Name = name,
				Foreground = new SolidColorBrush(ParseColorStr(foreColor)),
				Background = new SolidColorBrush(ParseColorStr(backColor)),
				Value = defaultVal,
				Height = 6,
				Margin = new Thickness(0, 2, 0, 2)
			};
			progressBar.ValueChanged += (sender, args) => valueChange?.Invoke(progressBar.Value);
			AddChild(progressBar);
		}

		public void AddCheckbox(string name, string text, bool defaultVal, string foreColor, string backColor,
			Action<bool, string> valueChange)
		{
			Grid grid = new Grid();
			grid.Name = name;
			grid.Background = new SolidColorBrush(ParseColorStr(backColor));
			CheckBox checkBox = new CheckBox()
			{
				Content = text,
				IsChecked = defaultVal,
				Foreground = new SolidColorBrush(ParseColorStr(foreColor)),
				Background = new SolidColorBrush(Colors.Transparent),
				Style = Resources["CheckboxStyle"] as Style
			};
			checkBox.Click += (sender, args) => valueChange?.Invoke(checkBox.IsChecked ?? false, name);
			grid.Children.Add(checkBox);
			AddChild(grid);
		}

		public void AddCombox(string name, string foreColor, string backColor, object[] items, Action<string, int, string> onChange)
		{
			ComboBox comboBox = new ComboBox()
			{
				Name = name,
				Style = Resources["ComboBoxStyle"] as Style,
				Foreground = new SolidColorBrush(ParseColorStr(foreColor)),
				Background = new SolidColorBrush(ParseColorStr(backColor)),
				Padding = new Thickness(5, 1, 5, 1)
			};
			foreach (var item in items)
			{
				comboBox.Items.Add(item);
			}

			if (comboBox.Items.Count > 0)
			{
				comboBox.SelectedIndex = 0;
			}

			comboBox.SelectionChanged += (sender, args) =>
			{
				onChange?.Invoke(name, comboBox.SelectedIndex, comboBox.Text);
			};
			AddChild(comboBox);
		}

		public void AddSlider(string name, int val, string foreColor, string backColor, Action<double, double> dragEvent)
		{
			if (val < 0) val = 0;
			if (val > 100) val = 100;
			Slider slider = new Slider()
			{
				Name = name,
				Value = val,
				Maximum = 100,
				Height = 12,
				Style = Resources["SliderStyle1"] as Style,
				Foreground = new SolidColorBrush(ParseColorStr(foreColor)),
				Background = new SolidColorBrush(ParseColorStr(backColor)),
				Padding = new Thickness(0, 2, 0, 2)
			};
			slider.IsMoveToPointEnabled = true;
			double oldVal = val, newVal = 0;
			bool isDown = false;
			slider.AddHandler(Slider.PreviewMouseDownEvent, new MouseButtonEventHandler((obj, e) =>
			{
				isDown = true;
			}), true);
			slider.ValueChanged += (sender, e) =>
			{
				if (isDown)
				{
					oldVal = e.OldValue;
					isDown = false;
				}
			};
			slider.AddHandler(MouseLeftButtonUpEvent, new MouseButtonEventHandler((obj, e) =>
			{
				newVal = slider.Value;
				dragEvent?.Invoke(oldVal, newVal);
			}), true);
			AddChild(slider);
		}

		/// <summary>
		/// 添加一个组件
		/// </summary>
		/// <param name="element">组件</param>
		public void AddControl(UIElement element)
		{
			if (element != null)
			{
				AddChild(element);
			}
		}


		// 设置窗体背景色
		public void SetBackColor(string color)
		{
			this.Background = new SolidColorBrush(ParseColorStr(color));
		}

		// 设置底部导航栏
		public void SetFooterBar(UIElement element)
		{
			footerView.Children.Clear();
			footerView.Children.Add(element);
		}

		// 切换底部功能栏的显示状态
		public void SwitchFooterBarState(Visibility visibility)
		{
			if (visibility == Visibility.Visible)
			{
				Grid.SetRowSpan(sv, 1);
			}
			else
			{
				Grid.SetRowSpan(sv, 2);
			}
			footerView.Visibility = visibility;
		}


		/// <summary>
		/// 解析颜色字符串
		/// </summary>
		/// <param name="color">颜色字符串如；#FF0000</param>
		/// <returns></returns>
		public static Color ParseColorStr(string color)
		{
			try
			{
				return (Color)ColorConverter.ConvertFromString(color);
			}
			catch
			{
				throw new Exception($"[{color}]颜色值格式不正确!");
			}
		}
	}
}
